package com.qingcloud.fexecutor.base.handler.statics;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.*;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.qingcloud.base.exception.WamingException;
import com.qingcloud.fexecutor.base.handler.ApiHandler;
import com.qingcloud.fexecutor.base.handler.ResultJsonBean;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.net.HttpCookie;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.Map;

/**
 * 动态API执行
 */
public class StaticApiHandler implements ApiHandler {

    private static final Logger logger = LoggerFactory.getLogger(StaticApiHandler.class);

    //真实URL
    private String url;

    //请求方法
    private String method;

    public StaticApiHandler(String url, String method) {
        this.url = url;
        this.method = method;
    }

    /**
     * 动态脚本API执行入口
     */
    @Override
    public Object invoke(HttpServletRequest request, HttpServletResponse response,
                         Map<String, String> headerMap, Map<String, Object> querys,
                         Map<String, Object> forms, Map<String, Object> paths,
                         Object bodyValue) throws Throwable {
        long startTime = System.currentTimeMillis();
        //path参数
        if (CollUtil.isNotEmpty(paths)) {
            for (Map.Entry<String, Object> entry : paths.entrySet()) {
                this.url = this.url.replace("{" + entry.getKey() + "}", String.valueOf(entry.getValue()));
            }
        }
        //构建HTTP请求
        if (CollUtil.isNotEmpty(querys)) {
            this.url = this.url + "?" + HttpUtil.toParams(querys);
        }
        logger.info("请求地址: {}", this.url);
        logger.info("请求方法: {}", this.method);
        HttpRequest httpRequest = new HttpRequest(this.url);
        httpRequest.setMethod(Method.valueOf(this.method.toUpperCase()));
        if (CollUtil.isNotEmpty(headerMap)) {
            httpRequest.headerMap(headerMap, true);
            logger.info("请求头: {}", JSONObject.toJSONString(headerMap));
        }
        if (CollUtil.isNotEmpty(forms)) {
            httpRequest.form(forms);
            logger.info("表单参数: {}", JSONObject.toJSONString(forms));
        }
        if (bodyValue != null) {
            httpRequest.body(JSONObject.toJSONString(bodyValue));
            logger.info("请求体: {}", JSONObject.toJSONString(forms));
        }
        HttpResponse execute = httpRequest.execute().sync();
        Object result = afterCompletion(response, execute);
        //当前时间
        long timestamp = System.currentTimeMillis();
        ResultJsonBean jsonBean = new ResultJsonBean();
        jsonBean.setCode(HttpStatus.HTTP_OK);
        jsonBean.setData(result);
        jsonBean.setFinishTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(timestamp));
        jsonBean.setExecuteTime((int) (timestamp - startTime));
        jsonBean.setRequestTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(startTime));
        return jsonBean;
    }

    /**
     * 处理静态API响应
     */
    private Object afterCompletion(HttpServletResponse response, HttpResponse resultResponse) {
        logger.info("开始执行API");
        //header
        Map<String, List<String>> headers = resultResponse.headers();
        if (CollUtil.isNotEmpty(headers)) {
            logger.info("响应结果header: {}", JSONObject.toJSONString(headers));
            for (Map.Entry<String, List<String>> entry : headers.entrySet()) {
                if (entry.getKey() != null && !"Content-Encoding".equalsIgnoreCase(entry.getKey())
                        && !"Content-Type".equalsIgnoreCase(entry.getKey())
                        && !"Content-Length".equalsIgnoreCase(entry.getKey())) {
                    response.addHeader(entry.getKey(), CollUtil.join(entry.getValue(), ","));
                }
            }
        }
        //cookie
        List<HttpCookie> cookies = resultResponse.getCookies();
        if (CollUtil.isNotEmpty(cookies)) {
            for (HttpCookie item : cookies) {
                logger.info("响应cookie: {}={}", item.getName(), item.getValue());
                Cookie cookie = new Cookie(item.getName(), item.getValue());
                cookie.setHttpOnly(cookie.isHttpOnly());
                cookie.setVersion(item.getVersion());
                cookie.setComment(item.getComment());
                cookie.setPath("/");
                cookie.setMaxAge((int) item.getMaxAge());
                cookie.setSecure(item.getSecure());
                response.addCookie(cookie);
            }
        }
        int status = resultResponse.getStatus();
        response.setStatus(status);
        logger.info("结果状态码: {}", status);
        String body = resultResponse.body();
        logger.info("请求结果: {}", body);
        if (status == HttpStatus.HTTP_OK) {
            return parseResult(body);
        } else {
            throw new WamingException("API执行失败");
        }
    }

    /**
     * 格式化请求结果
     */
    private Object parseResult(String result) {
        if (StrUtil.isEmpty(result)) {
            return result;
        }
        if (result.trim().startsWith("{")) {
            return JSONObject.parseObject(result);
        }
        if (result.trim().startsWith("[")) {
            return JSONArray.parseArray(result);
        }
        return result;
    }
}
